from page.ui_control import Ui_control
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import cv2
import numpy as np
from operation.convert import Convert


class Control(QWidget, Ui_control):
    Signal_pushButton = pyqtSignal(int)
    Signal_send = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.comboBox_camera.currentTextChanged.connect(self.port)
        self.pushButton_camera.toggled.connect(self.camera_connect)
        self.is_camera_opened = False

        self.__timer = QTimer(self)
        self.__timer.timeout.connect(self.__queryFrame)
        self.__timer.setInterval(30)

        self.icol = (0, 143, 108, 59, 255, 255)
        self.font = cv2.FONT_HERSHEY_SIMPLEX
        self.X = [0] * 5
        self.Y = [0] * 5
        self.R = [0] * 5
        self.x0 = np.mean(self.X)
        self.y0 = np.mean(self.Y)
        self.r0 = np.mean(self.R)

    def port(self):
        port = self.comboBox_camera.currentText()
        return port

    def camera_connect(self):
        self.is_camera_opened = ~ self.is_camera_opened
        if self.is_camera_opened:
            if self.open_camera():
                self.__timer.start()
                self.pushButton_camera.setText('关闭')
                self.textBrowser_info.append('open success!')
            else:
                self.pushButton_camera.setChecked(False)
                self.is_camera_opened = ~ self.is_camera_opened
                self.textBrowser_info.append('camera is not open, please change a port.')
        else:
            if self.open_camera():
                self.__timer.stop()
                self.pushButton_camera.setText('打开')
                self.textBrowser_info.append('close success!')
            else:
                self.is_camera_opened = ~ self.is_camera_opened
                self.pushButton_camera.setChecked(False)

    def open_camera(self):
        port = int(self.comboBox_camera.currentText())
        self.cap = cv2.VideoCapture(port)
        if self.cap.isOpened():
            return True
        else:
            return False

    def __queryFrame(self):
        self.roi()
        img_rows, img_cols, channels = self.frame.shape
        bytesPerLine = channels * img_cols
        cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB, self.frame)
        QImg = QImage(self.frame.data, img_cols, img_rows, bytesPerLine, QImage.Format_RGB888)
        self.label_image.setPixmap(
            QPixmap.fromImage(QImg).scaled(self.label_image.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))

    def roi(self):
        ret, self.frame = self.cap.read()
        hsv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2HSV)
        lower_red = np.array([self.icol[0], self.icol[1], self.icol[2]])
        upper_red = np.array([self.icol[3], self.icol[4], self.icol[5]])
        mask = cv2.inRange(hsv, lower_red, upper_red)
        opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel=np.ones((5, 5), np.uint8))
        edges = cv2.Canny(opening, 50, 100)

        circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=10, minRadius=10, maxRadius=50)
        font = cv2.FONT_HERSHEY_SIMPLEX
        if circles is not None:
            for circles in circles[0]:
                self.frame = self.filters(circles)
        else:
            cv2.putText(self.frame, 'x: None y: None', (10, 30), font, 1, (0, 255, 0), 2, cv2.LINE_AA, 0)

    def filters(self, circle):
        x = int(circle[0])
        y = int(circle[1])
        r = int(circle[2])

        if abs(x - self.x0) < 4:
            self.X.pop(0)
            self.X.append(x)
        else:
            self.X = [x] * 5

        if abs(y - self.y0) < 4:
            self.Y.pop(0)
            self.Y.append(y)
        else:
            self.Y = [y] * 5

        if abs(r - self.r0) < 4:
            self.R.pop(0)
            self.R.append(r)
        else:
            self.R = [r] * 5

        x2 = round(np.mean(self.X))
        y2 = round(np.mean(self.Y))
        r2 = round(np.mean(self.R))

        if abs(self.x0 - x2) < 3:
            x0 = self.x0
        else:
            x0 = x2
            self.x0 = x2

        if abs(self.y0 - y2) < 3:
            y0 = self.y0
        else:
            y0 = y2
            self.y0 = y2

        if abs(self.r0 - r2) < 3:
            r0 = self.r0
        else:
            r0 = r2
            self.r0 = r2

        cir = (x0, y0, r0)
        cv2.circle(self.frame, (cir[0], cir[1]), cir[2], (0, 0, 255), 3)
        cv2.circle(self.frame, (cir[0], cir[1]), 3, (255, 255, 0), -1)
        txt = 'x: ' + str(cir[0]) + 'y: ' + str(cir[1])
        self.lineEdit_x.setText(str(cir[0]))
        self.lineEdit_y.setText(str(cir[1]))
        cv2.putText(self.frame, txt, (10, 30), self.font, 1, (0, 255, 0), 2, cv2.LINE_AA, 0)
        return self.frame

    def pwm_send(self, pwm):
        data = Convert.Pneumatic2Input(pwm)
        data = str(data) + 'a'
        self.Signal_send.emit(data)
